﻿
using Microsoft.CSharp.RuntimeBinder;
using NUnit.Framework.Legacy;

namespace BakeryInventoryTesting
{
    [TestFixture]
    public class Tests
    {
        /// <summary>
        /// 测试 BakeryItem 属性已正确设置和检索
        /// </summary>
        /// <param name="val"></param>
        [Test]
        public void TestBakeryItem()
        {
            dynamic bakeryItem = new BakeryItem();
            Assert.DoesNotThrow(() => bakeryItem.Name = "test-name");
            Assert.Throws<RuntimeBinderException>(() => bakeryItem.Name = 1);
            Assert.Throws<ArgumentNullException>(() => bakeryItem.Name = null);
            Assert.Throws<ArgumentNullException>(() => bakeryItem.Name = string.Empty);

            Assert.DoesNotThrow(() => bakeryItem.Price = 1);
            Assert.Throws<RuntimeBinderException>(() => bakeryItem.Price = "1");

            Assert.DoesNotThrow(() => bakeryItem.Quantity = 1);
            Assert.Throws<RuntimeBinderException>(() => bakeryItem.Quantity = "1");

            Assert.DoesNotThrow(() => bakeryItem.ExpirationDate = DateTime.Now);
            Assert.Throws<RuntimeBinderException>(() => bakeryItem.ExpirationDate = 1);
            Assert.Throws<RuntimeBinderException>(() => bakeryItem.ExpirationDate = "1");

            Assert.DoesNotThrow(() => bakeryItem.IsExpired());
            Assert.That(bakeryItem.IsExpired(), Is.TypeOf<bool>());

        }

        /// <summary>
        /// 测试 IsExpired方法可以准确判断某个项目是否过期
        /// </summary>
        [Test]
        [TestCase("2001/3/3", ExpectedResult = true)]
        [TestCase("2000/3/3", ExpectedResult = true)]
        [TestCase("2100/3/3", ExpectedResult = false)]
        public bool TestIsExpired(string expirationDate)
        {
            var item = new BakeryItem()
            {
                ExpirationDate = DateTime.Parse(expirationDate)
            };
            return item.IsExpired();

        }


        /// <summary>
        /// 测试 BakeryInventory 方法可以正确地添加、删除和计算物品的总价值
        /// </summary>
        [Test]
        public void TestBakeryInventory()
        {
            var cake = new BakeryItem()
            {
                Name = "cake",
                Price = 20,
                Quantity = 10,
                ExpirationDate = DateTime.Now.AddDays(3),
            };
            var bread = new BakeryItem()
            {
                Name = "bread",
                Price = 10,
                Quantity = 50,
                ExpirationDate = DateTime.Now.AddDays(7),
            };
            var bakeryInventory = new BakeryInventory();
            //测试添加cake不抛异常
            Assert.DoesNotThrow(() => bakeryInventory.AddItem(cake));
            //索引集合里面，是否存在cake对象，保证添加成功
            Assert.That(bakeryInventory.IndexOf(cake), Is.GreaterThan(-1));

            Assert.DoesNotThrow(() => bakeryInventory.AddItem(bread));
            Assert.That(bakeryInventory.IndexOf(bread), Is.GreaterThan(-1));

            var expectedTotalValue = cake.Price * cake.Quantity + bread.Price * bread.Quantity;
            Assert.That(bakeryInventory.GetTotalValue(), Is.EqualTo(expectedTotalValue));

            //测试删除cake 不抛异常
            Assert.DoesNotThrow(() => bakeryInventory.Remove(cake));
            //删除后，检测是否还存在，索引 结果为-1代表没有找到
            Assert.That(bakeryInventory.IndexOf(cake), Is.EqualTo(-1));

            expectedTotalValue = bread.Price * bread.Quantity;
            Assert.That(bakeryInventory.GetTotalValue(), Is.EqualTo(expectedTotalValue));
        }

        /// <summary>
        /// 测试边缘情况
        /// </summary>
        [Test]
        public void TestBound()
        {
            var bakeryInventory = new BakeryInventory();
            var cake = new BakeryItem()
            {
                Name = "cake",
                Price = 20,
                Quantity = 10,
                ExpirationDate = DateTime.Now.AddDays(3),
            };
            Assert.Throws<ArgumentException>(() => bakeryInventory.RemoveItem(cake), "删除不存在的项目，需要抛出ArgumentException");


            bakeryInventory.AddItem(cake);
            //判断重复添加
            Assert.Throws<ArgumentException>(() => bakeryInventory.AddItem(cake));
        }

    }
}
